#include "synccontroller.h"

#include "QtNetwork/QNetworkInterface"

#include "dao/aqembalagemprodutodao.h"
#include "dao/aqempresadao.h"
#include "dao/aqfornecedordao.h"
#include "dao/aqprodembalagemdao.h"
#include "dao/aqprodempresainfodao.h"
#include "dao/aqprodgrupodao.h"
#include "dao/aqprodutodao.h"
#include "dao/ssanotacaodao.h"
#include "dao/ssanotacaofotodao.h"
#include "dao/ssnotificacaodao.h"
#include "dao/sspassosdao.h"
#include "dao/ssrastreadordao.h"
#include "dao/trcoletadao.h"
#include "dao/trcoletaitemdao.h"
#include "dao/trforncoletadao.h"
#include "dao/trforncoletaitemdao.h"

#include "databasecreator.h"

#include "utils/utils.h"

#define CONNECT_SERVICE_SIGNALS(serviceName) \
QObject::connect(&service##serviceName,SIGNAL(responseReceived(const QByteArray&)), \
                 this,SLOT(serviceName##Received(const QByteArray &))); \
QObject::connect(&service##serviceName,SIGNAL(networkError(QNetworkReply::NetworkError)), \
                 this,SLOT(serviceName##Error(QNetworkReply::NetworkError)));

#define IMPORT_CSV(nomeEntidade, response) \
{ \
    nomeEntidade##DAO dao; \
    if(!importCSV(&dao,QString(response),#nomeEntidade)) return; \
}

#define POST_CSV(nomeEntidade,where) \
{ \
    nomeEntidade##DAO daoEntidade; \
    if(!postCSV(&daoEntidade,service##nomeEntidade,#nomeEntidade,where)) return; \
}

SyncController::SyncController(QObject *parent) :
    QObject(parent)
{
    QString mac = getMacAddress();

    serviceAQEmbalagemProduto.setUrl(MAIN_URL "/AQEmbalagemProduto?UID="+mac);
    serviceAQEmpresa.setUrl(MAIN_URL "/AQEmpresa?UID="+mac);
    serviceAQFornecedor.setUrl(MAIN_URL "/AQFornecedor?UID="+mac);
    serviceAQProdEmbalagem.setUrl(MAIN_URL "/AQProdEmbalagem?UID="+mac);
    serviceAQProdEmpresaInfo.setUrl(MAIN_URL "/AQProdEmpresaInfo?UID="+mac);
    serviceAQProdGrupo.setUrl(MAIN_URL "/AQProdGrupo?UID="+mac);
    serviceAQProduto.setUrl(MAIN_URL "/AQProduto?UID="+mac);
    serviceTRCOLETA.setUrl(MAIN_URL "/TRCOLETA?UID="+mac);
    serviceTRCOLETAITEM.setUrl(MAIN_URL "/TRCOLETAITEM?UID="+mac);
    serviceTRFORNCOLETA.setUrl(MAIN_URL "/TRFORNCOLETA?UID="+mac);
    serviceTRFORNCOLETAITEM.setUrl(MAIN_URL "/TRFORNCOLETAITEM?UID="+mac);
    serviceSSAnotacao.setUrl(MAIN_URL "/SSAnotacao?UID="+mac);
    serviceSSAnotacaoFoto.setUrl(MAIN_URL "/SSAnotacaoFoto?UID="+mac);
    serviceSSNotificacao.setUrl(MAIN_URL "/SSNotificacao?UID="+mac);
    serviceSSPassos.setUrl(MAIN_URL "/SSPassos?UID="+mac);
    serviceSSRastreador.setUrl(MAIN_URL "/SSRastreador?UID="+mac);

    CONNECT_SERVICE_SIGNALS(AQEmbalagemProduto);
    CONNECT_SERVICE_SIGNALS(AQEmpresa);
    CONNECT_SERVICE_SIGNALS(AQFornecedor);
    CONNECT_SERVICE_SIGNALS(AQProdEmbalagem);
    CONNECT_SERVICE_SIGNALS(AQProdEmpresaInfo);
    CONNECT_SERVICE_SIGNALS(AQProdGrupo);
    CONNECT_SERVICE_SIGNALS(AQProduto);
    CONNECT_SERVICE_SIGNALS(TRCOLETA);
    CONNECT_SERVICE_SIGNALS(TRCOLETAITEM);
    CONNECT_SERVICE_SIGNALS(TRFORNCOLETA);
    CONNECT_SERVICE_SIGNALS(TRFORNCOLETAITEM);
    CONNECT_SERVICE_SIGNALS(SSAnotacao);
    CONNECT_SERVICE_SIGNALS(SSAnotacaoFoto);
    CONNECT_SERVICE_SIGNALS(SSNotificacao);
    CONNECT_SERVICE_SIGNALS(SSPassos);
    CONNECT_SERVICE_SIGNALS(SSRastreador);
}

QString SyncController::getMacAddress()
{
    QString result;
    foreach(QNetworkInterface interface, QNetworkInterface::allInterfaces())
    {
        if(interface.flags() & QNetworkInterface::IsLoopBack) continue;
        if(interface.hardwareAddress().length()>1) {
            result = interface.hardwareAddress();
            break;
        }
    }
    return result;
}

void SyncController::createDB() {
    DatabaseCreator c;
    QSqlError e = c.createDatabase();
    if(e.isValid()) {
        qDebug(e.text().toUtf8());
    }
}

template<class T>
bool SyncController::importCSV(T *dao, QString response, QString nomeEntidade)
{
    try {
        if(response.startsWith("{\"error\":")) {
            emit loadError();
            return false;
        }
        dao->importCSV(QString(response));
    } catch(DatabaseException& e) { \
        qDebug(QString("Erro importando os dados de ").append(nomeEntidade).toUtf8());
        emit loadError();
        return false;
    }

    return true;
}

template<class T>
bool SyncController::postCSV(T *daoEntidade, GenericService &genericService, QString nomeEntidade, QString where)
{
    try {
        QString content = daoEntidade->createCSV(where);
        content = Utils::StringMD5(content) + "\n" + content;
        genericService.post(&service,content);
    } catch(DatabaseException& e) {
        qDebug(QString("Erro exportandos os dados de ").append(nomeEntidade).toUtf8());
        emit sendError();
        return false;
    }

    return true;
}

void SyncController::startLoad() {
    serviceAQEmbalagemProduto.get(&service);
}

void SyncController::startSend() {
    getMacAddress();
    POST_CSV(TRCOLETA,"Finalizada='1'");
}

//

void SyncController::AQEmbalagemProdutoReceived(const QByteArray &response) {
    IMPORT_CSV(AQEmbalagemProduto,response);
    serviceAQEmpresa.get(&service);
}

void SyncController::AQEmbalagemProdutoError(QNetworkReply::NetworkError err) {
    emit loadError();
}

//

void SyncController::AQEmpresaReceived(const QByteArray &response) {
    IMPORT_CSV(AQEmpresa,response);
    serviceAQFornecedor.get(&service);
}

void SyncController::AQEmpresaError(QNetworkReply::NetworkError err) {
    emit loadError();
}

//

void SyncController::AQFornecedorReceived(const QByteArray &response) {
    IMPORT_CSV(AQFornecedor,response);
    serviceAQProdEmbalagem.get(&service);
}

void SyncController::AQFornecedorError(QNetworkReply::NetworkError err) {
    emit loadError();
}

//

void SyncController::AQProdEmbalagemReceived(const QByteArray &response) {
    IMPORT_CSV(AQProdEmbalagem,response);
    serviceAQProdEmpresaInfo.get(&service);
}

void SyncController::AQProdEmbalagemError(QNetworkReply::NetworkError err) {
    emit loadError();
}

//

void SyncController::AQProdEmpresaInfoReceived(const QByteArray &response) {
    IMPORT_CSV(AQProdEmpresaInfo,response);
    serviceAQProdGrupo.get(&service);
}

void SyncController::AQProdEmpresaInfoError(QNetworkReply::NetworkError err) {
    emit loadError();
}

//

void SyncController::AQProdGrupoReceived(const QByteArray &response) {
    IMPORT_CSV(AQProdGrupo,response);
    serviceAQProduto.get(&service);
}

void SyncController::AQProdGrupoError(QNetworkReply::NetworkError err) {
    emit loadError();
}

//

void SyncController::AQProdutoReceived(const QByteArray &response) {
    IMPORT_CSV(AQProduto,response);
    serviceTRFORNCOLETA.get(&service);
}

void SyncController::AQProdutoError(QNetworkReply::NetworkError err) {
    emit loadError();
}

//

void SyncController::TRFORNCOLETAReceived(const QByteArray &response) {
    IMPORT_CSV(TRFORNCOLETA,response);
    serviceTRFORNCOLETAITEM.get(&service);
}

void SyncController::TRFORNCOLETAError(QNetworkReply::NetworkError err) {
    emit loadError();
}

//

void SyncController::TRFORNCOLETAITEMReceived(const QByteArray &response) {
    IMPORT_CSV(TRFORNCOLETAITEM,response);
    emit loadComplete();
}

void SyncController::TRFORNCOLETAITEMError(QNetworkReply::NetworkError err) {
    emit loadError();
}

//

void SyncController::TRCOLETAReceived(const QByteArray &response) {
    TRCOLETADAO dao;
    dao.deleteAll("Finalizada='1'");

    POST_CSV(TRCOLETAITEM,"Finalizada='1'");
}

void SyncController::TRCOLETAError(QNetworkReply::NetworkError err) {
    emit loadError();
}

//

void SyncController::TRCOLETAITEMReceived(const QByteArray &response) {
    TRCOLETAITEMDAO dao;
    dao.deleteAll("Finalizada='1'");

    emit sendComplete();
}

void SyncController::TRCOLETAITEMError(QNetworkReply::NetworkError err) {
    emit loadError();
}

/***NAO USADOS***/

//

void SyncController::SSAnotacaoReceived(const QByteArray &response) {
    POST_CSV(SSAnotacaoFoto,"");
}

void SyncController::SSAnotacaoError(QNetworkReply::NetworkError err) {
    emit sendError();
}

//

void SyncController::SSAnotacaoFotoReceived(const QByteArray &response) {
    POST_CSV(SSNotificacao,"");
}

void SyncController::SSAnotacaoFotoError(QNetworkReply::NetworkError err) {
    emit sendError();
}

//

void SyncController::SSNotificacaoReceived(const QByteArray &response) {
    POST_CSV(SSPassos,"");
}

void SyncController::SSNotificacaoError(QNetworkReply::NetworkError err) {
    emit sendError();
}

//

void SyncController::SSPassosReceived(const QByteArray &response) {
    POST_CSV(SSRastreador,"");
}

void SyncController::SSPassosError(QNetworkReply::NetworkError err) {
    emit sendError();
}

//

void SyncController::SSRastreadorReceived(const QByteArray &response) {
    emit sendComplete();
}

void SyncController::SSRastreadorError(QNetworkReply::NetworkError err) {
    emit sendError();
}
